From 992d3fda6b2fc4ac88deb7f150138e06aa6d38ab Mon Sep 17 00:00:00 2001 From: robertl Date: Mon, 27 Nov 2006 01:00:12 +0000 Subject: [PATCH] Paul Tomblin updates CoPilot code.. --- copilot.c | 210 ++++++++++++++++++++++++++++++------- defs.h | 6 ++ util.c | 47 +++++++++ xmldoc/formats/copilot.xml | 3 + 4 files changed, 230 insertions(+), 36 deletions(-) diff --git a/copilot.c b/copilot.c index b1b1c903b..75412523a 100644 --- a/copilot.c +++ b/copilot.c @@ -25,17 +25,40 @@ #include "coldsync/pdb.h" #include "grtcirc.h" -#define MYNAME "CoPilot Waypoint" -#define MYTYPE 0x77617970 /* wayp */ -#define MYCREATOR 0x47584255 /* GXBU */ +#define MYNAME "CoPilot Waypoint" +#define wayp_TYPE 0x77617970 /* wayp */ +#define swpu_TYPE 0x73777075 /* swpu */ +#define GXPU_CREATOR 0x47584255 /* GXBU */ +#define AP_P_CREATOR 0x41502d50 /* AP-P */ -struct record { +struct record0 { + pdb_double latitude; /* PDB double format, */ + pdb_double longitude; /* similarly, neg = east */ + pdb_double magvar; /* magnetic variation in degrees, neg = east */ + udword elevation; /* feet */ +}; + +struct record1 { + pdb_double latitude; /* PDB double format, */ + pdb_double longitude; /* similarly, neg = east */ + pdb_double magvar; /* magnetic variation in degrees, neg = east */ + pdb_double elevation; /* feet */ +}; + +struct record3 { pdb_double latitude; /* PDB double format, */ pdb_double longitude; /* similarly, neg = east */ pdb_double magvar; /* magnetic variation in degrees, neg = east */ pdb_double elevation; /* feet */ - char flags; + char flags; /* flags */ +}; + +struct record4 { + pdb_double latitude; /* PDB double format, */ + pdb_double longitude; /* similarly, neg = east */ + pdb_float magvar; /* magnetic variation in degrees, neg = east */ + pdb_float elevation; /* feet */ }; static FILE *file_in; @@ -69,10 +92,124 @@ wr_deinit(void) fclose(file_out); } +static waypoint* +read_version0(ubyte* data) +{ + char *vdata; + waypoint *wpt_tmp; + struct record0* rec = (struct record0*)data; + + wpt_tmp = waypt_new(); + + wpt_tmp->longitude = + DEG(-pdb_read_double(&rec->longitude)); + wpt_tmp->latitude = + DEG(pdb_read_double(&rec->latitude)); + wpt_tmp->altitude = FEET_TO_METERS(be_read32(&rec->elevation)); + + vdata = (char *) data + sizeof(*rec); + + wpt_tmp->shortname = xstrdup(vdata); + vdata = vdata + strlen(vdata) + 1; + + wpt_tmp->description = xstrdup(vdata); + vdata = vdata + strlen(vdata) + 1; + + wpt_tmp->notes = NULL; + + return wpt_tmp; +} + +static waypoint* +read_version1(ubyte* data) +{ + char *vdata; + waypoint *wpt_tmp; + struct record1* rec = (struct record1*)data; + + wpt_tmp = waypt_new(); + + wpt_tmp->longitude = + DEG(-pdb_read_double(&rec->longitude)); + wpt_tmp->latitude = + DEG(pdb_read_double(&rec->latitude)); + wpt_tmp->altitude = + FEET_TO_METERS(pdb_read_double(&rec->elevation)); + + vdata = (char *) data + sizeof(*rec); + + wpt_tmp->shortname = xstrdup(vdata); + vdata = vdata + strlen(vdata) + 1; + + wpt_tmp->description = xstrdup(vdata); + vdata = vdata + strlen(vdata) + 1; + + wpt_tmp->notes = xstrdup(vdata); + + return wpt_tmp; +} + +static waypoint* +read_version3(ubyte* data) +{ + char *vdata; + waypoint *wpt_tmp; + struct record3* rec = (struct record3*)data; + + wpt_tmp = waypt_new(); + + wpt_tmp->longitude = + DEG(-pdb_read_double(&rec->longitude)); + wpt_tmp->latitude = + DEG(pdb_read_double(&rec->latitude)); + wpt_tmp->altitude = + FEET_TO_METERS(pdb_read_double(&rec->elevation)); + + vdata = (char *) data + sizeof(*rec); + + wpt_tmp->shortname = xstrdup(vdata); + vdata = vdata + strlen(vdata) + 1; + + wpt_tmp->description = xstrdup(vdata); + vdata = vdata + strlen(vdata) + 1; + + wpt_tmp->notes = xstrdup(vdata); + + return wpt_tmp; +} + +static waypoint* +read_version4(ubyte* data) +{ + char *vdata; + waypoint *wpt_tmp; + struct record4* rec = (struct record4*)data; + + wpt_tmp = waypt_new(); + + wpt_tmp->longitude = + DEG(-pdb_read_double(&rec->longitude)); + wpt_tmp->latitude = + DEG(pdb_read_double(&rec->latitude)); + wpt_tmp->altitude = + FEET_TO_METERS(pdb_read_float(&rec->elevation)); + + vdata = (char *) data + sizeof(*rec); + + wpt_tmp->shortname = xstrdup(vdata); + vdata = vdata + strlen(vdata) + 1; + + wpt_tmp->description = xstrdup(vdata); + vdata = vdata + strlen(vdata) + 1; + + wpt_tmp->notes = xstrdup(vdata); + + return wpt_tmp; +} + static void data_read(void) { - struct record *rec; struct pdb *pdb; struct pdb_record *pdb_rec; @@ -80,45 +217,46 @@ data_read(void) fatal(MYNAME ": pdb_Read failed\n"); } - if ((pdb->creator != MYCREATOR) || (pdb->type != MYTYPE)) { + if ((pdb->creator != GXPU_CREATOR && pdb->creator != AP_P_CREATOR) || + (pdb->type != wayp_TYPE && pdb->type != swpu_TYPE)) { fatal(MYNAME ": Not a CoPilot file.\n"); } + if (pdb->version > 4) { + fatal(MYNAME ": %d is not a known version.\n", pdb->version); + } + for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) { waypoint *wpt_tmp; - char *vdata; - - wpt_tmp = waypt_new(); - - rec = (struct record *) pdb_rec->data; - wpt_tmp->longitude = - DEG(-pdb_read_double(&rec->longitude)); - wpt_tmp->latitude = - DEG(pdb_read_double(&rec->latitude)); - wpt_tmp->altitude = - pdb_read_double(&rec->elevation) * .3048; - - vdata = (char *) pdb_rec->data + sizeof(*rec); - - wpt_tmp->shortname = xstrdup(vdata); - vdata = vdata + strlen(vdata) + 1; - - wpt_tmp->description = xstrdup(vdata); - vdata = vdata + strlen(vdata) + 1; - - wpt_tmp->notes = xstrdup(vdata); + switch (pdb->version) + { + case 0: + wpt_tmp = read_version0(pdb_rec->data); + break; + case 1: + case 2: + wpt_tmp = read_version1(pdb_rec->data); + break; + case 3: + wpt_tmp = read_version3(pdb_rec->data); + break; + case 4: + wpt_tmp = read_version4(pdb_rec->data); + break; + default: + fatal(MYNAME ": Unknown version %d.\n", pdb->version); + } waypt_add(wpt_tmp); } free_pdb(pdb); } - static void copilot_writewpt(const waypoint *wpt) { - struct record *rec; + struct record4 *rec; static int ct = 0; char *vdata; @@ -126,9 +264,9 @@ copilot_writewpt(const waypoint *wpt) pdb_write_double(&rec->latitude, RAD(wpt->latitude)); pdb_write_double(&rec->longitude, RAD(-wpt->longitude)); - pdb_write_double(&rec->elevation, - wpt->altitude / .3048); - pdb_write_double(&rec->magvar, 0); + pdb_write_float(&rec->magvar, 0); + pdb_write_float(&rec->elevation, + METERS_TO_FEET(wpt->altitude)); vdata = (char *)rec + sizeof(*rec); if ( wpt->shortname ) { @@ -180,9 +318,9 @@ data_write(void) opdb->name[PDB_DBNAMELEN-1] = 0; opdb->attributes = PDB_ATTR_BACKUP; opdb->ctime = opdb->mtime = current_time() + 2082844800U; - opdb->type = MYTYPE; - opdb->creator = MYCREATOR; - opdb->version = 0; + opdb->type = wayp_TYPE; + opdb->creator = GXPU_CREATOR; + opdb->version = 4; waypt_disp_all(copilot_writewpt); diff --git a/defs.h b/defs.h index daa85fef4..ce53d5f21 100644 --- a/defs.h +++ b/defs.h @@ -785,6 +785,10 @@ typedef struct { unsigned char data[8]; } pdb_double; +typedef struct { + unsigned char data[4]; +} pdb_float; + /* * Protypes for Endianness helpers. */ @@ -798,8 +802,10 @@ void be_write16(void *pp, const unsigned i); void be_write32(void *pp, const unsigned i); void le_write16(void *pp, const unsigned i); void le_write32(void *pp, const unsigned i); +float pdb_read_float(void *p); double pdb_read_double(void *p); void pdb_write_double(void *pp, double d); +void pdb_write_float(void *pp, float d); double le_read_double(void *p); double be_read_double(void *p); diff --git a/util.c b/util.c index 2ff419df2..9259e5ea6 100644 --- a/util.c +++ b/util.c @@ -890,6 +890,29 @@ endian_read_double(void* ptr, int read_le) return ret; } +float +endian_read_float(void* ptr, int read_le) +{ + float ret; + char r[4]; + void *p; + int i; + + if ( i_am_little_endian == read_le ) { + p = ptr; + } + else { + for (i = 0; i < 4; i++) + { + r[i] = ((char*)ptr)[3-i]; + } + p = r; + } + + memcpy(&ret, p, 4); + return ret; +} + void endian_write_double(void* ptr, double d, int write_le) { @@ -908,9 +931,30 @@ endian_write_double(void* ptr, double d, int write_le) } } +void +endian_write_float(void* ptr, float f, int write_le) +{ + char *r = (char *)(void *)&f; + int i; + char *optr = ptr; + + if ( i_am_little_endian == write_le ) { + memcpy( ptr, &f, 4); + } + else { + for (i = 0; i < 4; i++) + { + *optr++ = r[3-i]; + } + } +} + double pdb_read_double( void *ptr ) {return endian_read_double(ptr, 0);} +float +pdb_read_float( void *ptr ) {return endian_read_float(ptr, 0);} + double le_read_double( void *ptr ) {return endian_read_double(ptr,1);} @@ -920,6 +964,9 @@ be_read_double( void *ptr ) {return endian_read_double(ptr,0);} void pdb_write_double( void *ptr, double d ) {endian_write_double(ptr,d,0);} +void +pdb_write_float( void *ptr, float f ) {endian_write_float(ptr,f,0);} + void le_write_double( void *ptr, double d ) {endian_write_double(ptr,d,1);} diff --git a/xmldoc/formats/copilot.xml b/xmldoc/formats/copilot.xml index 4837f1627..6eb5272de 100644 --- a/xmldoc/formats/copilot.xml +++ b/xmldoc/formats/copilot.xml @@ -5,6 +5,9 @@ Planner for Palm/OS" databases into other formats. You probably should not use this to write CoPilot databases, although the code is there, because GPSBabel doesn't convert magnetic declination values. +This version now reads all CoPilot file versions up to 4, but only +writes version 4 files. If you have a need for a version flag, please let +me know. Questions, bug reports, etc, to ptomblin at xcski.com -- 2.30.2